package com.hp.bon.sgw.dr.config;

import java.io.PrintStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hp.bon.sgw.dr.config.MdrmgrConst.DrDirect;
public class MdrmgrSrvCfg
{
	public static final Logger Log = LoggerFactory.getLogger(MdrmgrSrvCfg.class);
	public Map<String, MdrNodeInfo> _NodeMap = new HashMap<String, MdrNodeInfo>();;//nodeName-->node
	public Map<String, MdrNodeInfo> _RequestToBuzCapMap = new HashMap<String, MdrNodeInfo>();;//cap-->node
	public Map<String, MdrNodeInfo> _RequestFromBuzCapMap = new HashMap<String, MdrNodeInfo>();;//cap-->node

  private long _PrvSz = 0L;
  private long _PrvTs = 0L;
  private String otherDrProxy = null;

  private static String fileName = "./etc/dr/mdr_service_cfg.xml";
  private static MdrmgrSrvCfg instance;

  public String getOtherDrProxy()
  {
    return this.otherDrProxy;
  }

  public String asString() {
    StringBuilder sb_ = new StringBuilder();
    sb_.append(String.format("contents of MdrmgrSrvCfg:%n", new Object[0]));
    sb_.append(String.format(" _PrvSz=%d, _PrvTs=%d [%s], %d entries in _NodeMap%n", new Object[] { Long.valueOf(this._PrvSz), Long.valueOf(this._PrvTs), 
      PubMethod.Long2Str(this._PrvTs, PubMethod.TimeStrFmt.Fmt23), Integer.valueOf(this._NodeMap.size()) }));
    int i = 0;
    for (String s : this._NodeMap.keySet()) {
      sb_.append(String.format(" No.%2d, {}", new Object[] { Integer.valueOf(++i), ((MdrNodeInfo)this._NodeMap.get(s)).toString() }));
    }
    return sb_.substring(0);
  }

  public boolean RefreshCfg(boolean on_stat_change)
  {
    boolean rc_ = true;
    SAXReader sax_reader_ = new SAXReader();
    try {
      Document doc_ = sax_reader_.read(fileName);
      Log.info("srv cfg file [{}] parsed", fileName);
      Element root_ = doc_.getRootElement();
      Map result_map_ = new TreeMap();

      Node otherDrProxyNode = root_.selectSingleNode("/target/otherDrProxy");
      this.otherDrProxy = otherDrProxyNode.valueOf("@name");

      String xpath_ = "/target/node_group/node";
      List<Node> xml_node_list_ = root_.selectNodes(xpath_);
      Log.debug("{} nodes selected, xpath_=[{}]", Integer.valueOf(xml_node_list_.size()), xpath_);
      for (Node n : xml_node_list_) {
        MdrNodeInfo node_ = new MdrNodeInfo();
        node_._name = n.valueOf("@name").trim();
        node_._auditMode = n.valueOf("mdr_node_group/@AuditMode").trim();
        node_._duplex = n.valueOf("mdr_node_group/@Duplex").trim();
        node_._auditTimeout = (Long.parseLong(n.valueOf("mdr_node_group/@audit_timeout").trim()) * 1000L);
        node_._expTime = (Long.parseLong(n.valueOf("mdr_node_group/@exp_time").trim()) * 3600L * 1000L);
        node_._queryCnt = Integer.parseInt(n.valueOf("mdr_node_group/@query_cnt").trim());

        String sub_xpath_ = "mdr_node_group/dr_node";
        List<Node> xml_sub_nodes_ = n.selectNodes(sub_xpath_);
        Log.info("{} nodes selected, xpath_=[{}/{}]", new Object[] { Integer.valueOf(xml_sub_nodes_.size()), xpath_, sub_xpath_ });
        for (Node s : xml_sub_nodes_) {
          String str_ = s.valueOf("@Location").trim();
          if (str_.equals("LOCAL")) {
            node_._localNodeNm = s.valueOf("@name");
            node_._localNodeDrStatus = s.valueOf("@DRStatus");
          } else if (str_.equals("PEER")) {
            node_._peerNodeNm = s.valueOf("@name");
            node_._peerNodeDrStatus = s.valueOf("@DRStatus");
          } else {
            Log.info("invalid attribute value [{}], xpath_=[{}/{}/@Location]", new Object[] { str_, xpath_, sub_xpath_ });
          }
        }

        sub_xpath_ = "mdr_capability/capbility";
        xml_sub_nodes_ = n.selectNodes(sub_xpath_);
        Log.info("{} nodes selected, xpath_=[{}/{}]", new Object[] { Integer.valueOf(xml_sub_nodes_.size()), xpath_, sub_xpath_ });
        for (Node s : xml_sub_nodes_) {
          String capName = s.valueOf("@name").trim();
          String str_ = s.valueOf("@r_flag");
          int flag = Integer.parseInt(str_);
          node_._capDrMap.put(capName, Integer.valueOf(flag));
        }

        sub_xpath_ = "capa_dependent/capbility";
        xml_sub_nodes_ = n.selectNodes(sub_xpath_);
        Log.debug("{} nodes selected, xpath_=[{}/{}]", new Object[] { Integer.valueOf(xml_sub_nodes_.size()), xpath_, sub_xpath_ });
        for (Node s : xml_sub_nodes_) {
          String str_ = s.valueOf("@name");
          node_._capDependentMap.put(str_, str_);
        }

        if (node_.isValid()) {
          result_map_.put(node_._name, node_);
          cap2NodeMap(node_);
        } else {
          Log.warn("validate MdrNodeInfo [{}] failed, xpath_=[{}]", node_._name, xpath_);
          rc_ = false;
        }

      }

      if (rc_) {
        this._NodeMap = result_map_;

        Log.info("srv cfg file [{}] refresh ok", fileName);
      }
    } catch (Exception e) {
      Log.warn("parse [{}] exception", fileName);
      rc_ = false;
    }
    return rc_;
  }

  public static MdrmgrSrvCfg getInstance()
  {
    if (instance == null) {
      instance = new MdrmgrSrvCfg();
      instance.RefreshCfg(true);
    }
    return instance;
  }

  private void cap2NodeMap(MdrNodeInfo node_)
  {
    for (Map.Entry entry : node_._capDrMap.entrySet())
    {
      String cap = (String)entry.getKey();
      int flag = ((Integer)entry.getValue()).intValue();
      if (flag == 1)
      {
        this._RequestToBuzCapMap.put(cap, node_);
      }
      else
      {
        this._RequestFromBuzCapMap.put(cap, node_);
      }
    }
  }

  public MdrNodeInfo queryNodeByRequestToBuzCap(String capName) {
    return (MdrNodeInfo)this._RequestToBuzCapMap.get(capName);
  }

  public MdrNodeInfo queryNodeByRequestFromBuzCap(String capName)
  {
    return (MdrNodeInfo)this._RequestFromBuzCapMap.get(capName);
  }

  public static void main(String[] args) {
    getInstance();

    MdrNodeInfo mdrNodeInfo = null;
    System.out.println(getInstance().asString());
  }
}
